using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

using Derm.Render;

namespace ShaderGen.Ui
{
	public partial class ProgramEditorBox : UserControl
	{
		public ProgramEditorBox()
		{
			InitializeComponent();
		}

		public ProgramEditorBox(ShaderLibraryProject libraryProject) : this()
		{
			mLibraryProject = libraryProject;
			UpdateControl();
		}

		public ShaderLibraryProgram LibraryProgram
		{
			get { return (mLibraryProgram); }
			set
			{
				mLibraryProgram = value;
				UpdateControl();
			}
		}

		private ShaderLibraryProject mLibraryProject;

		private ShaderLibraryProgram mLibraryProgram;

		private void UpdateControl()
		{
			UpdateObjectView();
		}

		private void UpdateCmbObject(ShaderLibraryObject.Stage shaderStage)
		{
			CmbObject.Items.Clear();
			if ((mLibraryProject == null) || (shaderStage == ShaderLibraryObject.Stage.Any))
				return;

			foreach (ShaderLibraryConfiguration libraryConfiguration in mLibraryProject.Libraries) {
				foreach (ShaderLibraryObject libraryObject in libraryConfiguration.Objects) {
					if ((libraryObject.ObjectStage == ShaderLibraryObject.Stage.Any) || (libraryObject.ObjectStage == shaderStage)) {
						CmbObject.Items.Add(libraryObject.ClassName);
					}
				}
			}
		}

		private void UpdateCmbObject(ShaderLibraryObject.Stage shaderStage, string selectedObject)
		{
			UpdateCmbObject(shaderStage);

			CmbObject.SelectedItem = selectedObject;
		}

		private void UpdateObjectView()
		{
			ObjectView.Items.Clear();

			if (mLibraryProgram != null)
				UpdateObjectView(ObjectView.Groups["GroupVertex"], mLibraryProgram.VertexShaders);

			if (mLibraryProgram != null)
				UpdateObjectView(ObjectView.Groups["GroupGeometry"], mLibraryProgram.GeometryShaders);

			if (mLibraryProgram != null)
				UpdateObjectView(ObjectView.Groups["GroupTessControl"], mLibraryProgram.TessControlShaders);

			if (mLibraryProgram != null)
				UpdateObjectView(ObjectView.Groups["GroupTessEval"], mLibraryProgram.TessEvalShaders);

			if (mLibraryProgram != null)
				UpdateObjectView(ObjectView.Groups["GroupFragment"], mLibraryProgram.FragmentShaders);
		}

		private void UpdateObjectView(ListViewGroup listViewGroup, IEnumerable<ShaderLibraryProgram.LibraryObjectRef> objectRefs)
		{
			ListViewItem libViewItem;

			foreach (ShaderLibraryProgram.LibraryObjectRef objectRef in objectRefs) {
				libViewItem = new ListViewItem(listViewGroup);
				libViewItem.Text = objectRef.ObjectId;
				libViewItem.Tag = objectRef;
				libViewItem.SubItems.Add(objectRef.Interface ?? String.Empty);

				ObjectView.Items.Add(libViewItem);
			}

			libViewItem = new ListViewItem(listViewGroup);
			libViewItem.Text = "Enter object id...";
			libViewItem.Font = new Font(FontFamily.GenericSansSerif, 6.0f, System.Drawing.FontStyle.Italic);
			ObjectView.Items.Add(libViewItem);
		}

		private void ObjectView_SelectedIndexChanged(object sender, EventArgs e)
		{
			ListView objectView = (ListView) sender;

			// No object selected, empty combo box
			if ((objectView.SelectedIndices.Count == 0) || (objectView.SelectedIndices[0] < 0)) {
				UpdateCmbObject(ShaderLibraryObject.Stage.Any);
				return;
			}

			ListViewItem objectViewItem = objectView.Items[objectView.SelectedIndices[0]];
			string selectedObject = null;

			if (objectViewItem.Tag is ShaderLibraryProgram.LibraryObjectRef) {
				ShaderLibraryProgram.LibraryObjectRef objectRef = (ShaderLibraryProgram.LibraryObjectRef) objectViewItem.Tag;
				selectedObject = objectRef.ObjectId;
			}

			if      (objectViewItem.Group.Name == "GroupVertex")
				UpdateCmbObject(ShaderLibraryObject.Stage.Vertex, selectedObject);
			else if (objectViewItem.Group.Name == "GroupGeometry")
				UpdateCmbObject(ShaderLibraryObject.Stage.Geometry, selectedObject);
			else if (objectViewItem.Group.Name == "GroupTessControl")
				UpdateCmbObject(ShaderLibraryObject.Stage.TessControl, selectedObject);
			else if (objectViewItem.Group.Name == "GroupTessEval")
				UpdateCmbObject(ShaderLibraryObject.Stage.TessEvaluation, selectedObject);
			else if (objectViewItem.Group.Name == "GroupFragment")
				UpdateCmbObject(ShaderLibraryObject.Stage.Fragment, selectedObject);
		}
	}
}
